﻿package bdz.projects.cbt
{
	import bdz.common.events.DispatchChannel;
	import bdz.common.model.AppEnvironment;
	import bdz.projects.cbt.core.CBTPlayer;
	import bdz.projects.cbt.core.CBTProduct;
	import bdz.projects.cbt.core.CBTProducts;
	import bdz.projects.cbt.core.ProductCollection;
	import bdz.projects.cbt.events.CBTGameEvent;
	import bdz.projects.cbt.events.CBTUIEvent;
	import bdz.projects.cbt.ui.CBTInventoryList;
	import bdz.projects.cbt.ui.CBTProductList;
	import bdz.projects.cbt.utils.CBTSounds;
	
	import flash.events.EventDispatcher;
	import flash.utils.setTimeout;

	public class CBTGame extends EventDispatcher{
		
		private static var instance:CBTGame;
		
		private var _maxDays:Number;
		private var _numDays:Number;
		private var _player:CBTPlayer;
		private var _products:CBTProducts;
		private var _location:String;
		private var _channel:DispatchChannel = DispatchChannel.getChannel();
		private var _locations:Array;
		
		private var _mortgageRate:Number;
		private var _paypalRate:Number;
		
		private var _travelCount:Number = 0;
		private var _transactionMade:Boolean = false;
		
		private var _selectedProduct:CBTProduct;
		private var _selectedInventory:ProductCollection;
		private var _productList:CBTProductList;
		private var _inventoryList:CBTInventoryList;
		public var finished:Boolean = false;
		public function CBTGame(se:SingletonEnforcer){
			super();
			createListeners();
		}
		public static function getInstance():CBTGame{
			if(instance == null){
				instance = new CBTGame(new SingletonEnforcer());
				instance._channel.addEventListener(CBTGameEvent.PRODUCTS_REFRESHED, instance.checkProbabilities);
			}
			return instance;
		}
		
		public function set player(p:CBTPlayer):void{
			_player = p;
		}
		public function set products(p:CBTProducts):void{
			_products = p;	
		}
		public function get products():CBTProducts{
			return _products;
		}
		public function get player():CBTPlayer{
			return _player;
		}
		private function checkProbabilities(evt:CBTGameEvent):void{
			
			if(_productList && _productList.dataProvider){
				var dp:Array =  _productList.dataProvider as Array;
				var _queue:Array = new Array();
				var counter:Number = 0;
				for each(var p:CBTProduct in dp){
					
					if(p.currentlyCheap){
						_queue[counter] = p;
						counter++;
					}else if(p.currentlyExpensive){
						_queue[counter] = p
						counter++;				
					}
				}
				if(_queue.length){
					var ep:CBTProduct = _queue[(Math.floor(Math.random()*_queue.length))];
					if(ep.currentlyCheap){
						_channel.dispatchEvent(new CBTGameEvent(CBTGameEvent.PRODUCT_REALLY_CHEAP, ep));
					}else{
						_channel.dispatchEvent(new CBTGameEvent(CBTGameEvent.PRODUCT_REALLY_EXPENSIVE, ep));	
					}
					CBTSounds.playBubble();
				}
			}
			
		}
		private function checkDayProgress():void{
			/*
			if(Math.floor((_numDays/_maxDays)*100) >= 25){
				
				if(_player.paypal.value < (_player.cash.value*.1)){		
					var steal:Boolean = MathUtils.randomPercentChance(Math.floor(5+Math.random()*3)*10);
				}
			}
			*/
			var _modValue:Number;
			if(_maxDays == 10){
				_modValue = 2;
			}
			if(_maxDays == 20){
				_modValue = 4;
			}
			if(_maxDays == 30){
				_modValue = 5;
			}
			if(_numDays%_modValue == 0){
				_channel.dispatchEvent(new CBTUIEvent(CBTUIEvent.SHOW_WAREHOUSE_UPGRADE, null));
				//skip steal
				return;
			}
			/*
			if(steal){
				dispatchEvent(new CBTGameEvent(CBTGameEvent.MONEY_STOLEN));
			}*/
		}
		private function setUpEndListeners():void{
			_channel.removeEventListener(CBTGameEvent.ITEM_SOLD, listenToEnd);
			_channel.removeEventListener(CBTGameEvent.MORTGAGE_CHANGE, listenToEnd);
			
			_channel.addEventListener(CBTGameEvent.ITEM_SOLD, listenToEnd);
			_channel.addEventListener(CBTGameEvent.MORTGAGE_CHANGE, listenToEnd);
		}
		private function listenToEnd(evt:CBTGameEvent):void{
			checkEndGame();
		}
		private function finalizeGame():void{
			
		}
		public function checkEndGame():void{
			
			var gdata:Object;
			if(_player.cash.value == 0 && _player.mortgage.value > 0){
				gdata = getGameData();
				gdata.failed = true;
				setTimeout(dispatchEvent, 100, new CBTGameEvent(CBTGameEvent.GAME_FINALIZED, gdata));
				return;
			}
			_player.cash.removeAmount(_player.mortgage.value);
			_player.mortgage.removeAmount(_player.mortgage.value);
			_player.cash.addAmount(_player.inventory.totalValue);
			/*
			if(_player.mortgage.value > 0){
				_channel.dispatchEvent(new CBTUIEvent(CBTUIEvent.NOTIFY_MORTGAGE));
				setUpEndListeners();
			}else if( _player.inventory.totalValue > 0){
				
				_channel.dispatchEvent(new CBTUIEvent(CBTUIEvent.NOTIFY_INVENTORY));
				setUpEndListeners();
			}else
			*/ 
			if(_player.totalWorth < 0){
				gdata = getGameData();
				gdata.failed = true;
				setTimeout(dispatchEvent, 100, new CBTGameEvent(CBTGameEvent.GAME_FINALIZED, gdata));	
			}else {
				gdata = getGameData();
				gdata.failed = false;
				setTimeout(dispatchEvent, 100, new CBTGameEvent(CBTGameEvent.GAME_FINALIZED, gdata));	
			}
			
				
			
		}
		private function getGameData():Object{
			var _gameData:Object = {};
			_gameData.player = _player;
			_gameData.products = _products;
			_gameData.numDays = _numDays;
			_gameData.maxDays = _maxDays;
			_gameData.location = _location;
			_gameData.inventory = _player.inventory;
			_gameData.selectedInventory = _selectedInventory;
			_gameData.selectedProduct = _selectedProduct;
			_gameData.productList = _productList;
			_gameData.inventoryList = _inventoryList;
			return _gameData;
		}
		
		private function createListeners():void{
			_channel.addEventListener(CBTUIEvent.PRODUCT_ITEM_SELECTED, onProductItemSelect);
			_channel.addEventListener(CBTUIEvent.INVENTORY_ITEM_SELECTED, onInventoryItemSelect);
		}
		private function resolveLocationChange():void{
			_numDays++;
			_travelCount++;
			
			
			_player.mortgage.addAmount(Math.floor(_player.mortgage.value*_mortgageRate));
			
			if((_maxDays-_numDays) == 0){
				_channel.dispatchEvent(new CBTGameEvent(CBTGameEvent.GAME_ENDED));
				checkEndGame();		
			}else{
				checkDayProgress();
			}
			_channel.dispatchEvent(new CBTGameEvent(CBTGameEvent.LOCATION_CHANGE));
			
		}
		private function onProductItemSelect(evt:CBTUIEvent):void{
			_selectedProduct = evt.data.info;
		}
		private function onInventoryItemSelect(evt:CBTUIEvent):void{
			_selectedInventory = evt.data.info;
		}
		public function startGame(n:Number, p:CBTPlayer, pr:CBTProducts, loc:String):void{
			_numDays = 0;
			_maxDays = n;
			_player = p;
			_products = pr;
			_location = loc;
			
			
			_channel.dispatchEvent(new CBTGameEvent(CBTGameEvent.GAME_STARTED, getGameData()));
			
			
		}
		public function warehouseUpgrade(amount:Number, mortg:Number):void{
			CBTSounds.playUpgrade();
			_player.inventory.upgradeCapacity(amount);
			_player.mortgage.addAmount(mortg);
			_channel.dispatchEvent(new CBTGameEvent(CBTGameEvent.WAREHOUSE_UPGRADE, getGameData()));
		}
		public function moneyStolen(amount:Number):void{
			_player.cash.removeAmount(amount);
			_channel.dispatchEvent(new CBTGameEvent(CBTGameEvent.MONEY_STOLEN, getGameData()));
		}
		public function itemSold(tot:Number, quan:Number, tocash:Boolean, pname:String):void{
			if(tocash){
				_player.cash.addAmount(tot);
			}else{
				_player.paypal.addAmount(tot);
			}
			_player.addSoldItem(pname, quan);
			_player.addFeedback(quan);
			_travelCount = 0;
			_channel.dispatchEvent(new CBTGameEvent(CBTGameEvent.ITEM_SOLD, getGameData()));
			
		}
		public function itemBought(p:CBTProduct, amount:Number):void{
			for(var i:Number = 0;i<amount;i++){
				_player.inventory.addProduct(p);
			}
			_player.addFeedback(1);
			_inventoryList.dataProvider = _player.inventory.productList;
			_travelCount = 0;
			_channel.dispatchEvent(new CBTGameEvent(CBTGameEvent.ITEM_BOUGHT, getGameData()));
			
		}
		public function paypalTransact():void{
			_channel.dispatchEvent(new CBTGameEvent(CBTGameEvent.PAYPAL_TRANSACT, getGameData()));
		}
		public function mortgageTransact():void{
			_channel.dispatchEvent(new CBTGameEvent(CBTGameEvent.MORTGAGE_CHANGE, getGameData()));
		}
		public function changeLocation(newloc:String):void{
			CBTSounds.playTravel();
			_location = newloc;
			if(_travelCount < 5){
				resolveLocationChange();
				_player.cash.removeAmount(AppEnvironment.getEnv().getSetting("travelFare"));
			}else{
				_travelCount = 0;
			}
			_channel.dispatchEvent(new CBTGameEvent(CBTGameEvent.GAME_CHANGE, getGameData()));
				
		}
		public function resetGame():void{
			
		}
		public function get daysLeft():Number{
			return _maxDays-_numDays;
		}
		public function get gameData():Object{
			return getGameData();
		}
		public function get currentLocation():String{
			return _location;
		}
		public function set mortgageRate(n:Number):void{
			_mortgageRate = n;
		}
		public function get mortgageRate():Number{
			return _mortgageRate;
		}
		public function set paypalRate(n:Number):void{
			_paypalRate = n;
		}
		public function get paypalRate():Number{
			return _paypalRate;
		}
		public function set inventoryList(il:CBTInventoryList):void{
			_inventoryList = il;
		}
		public function set productList(pl:CBTProductList):void{
			_productList = pl;
		}
		public function get maxDays():Number{
			return _maxDays;
		}
	}
}
internal class SingletonEnforcer {}